﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Web;

namespace com.aspnet
{
    public class OnlineUserItemEventArgs : System.EventArgs
    {
        public OnlineUserItem Item { get; set; }
    }

    public delegate void OnlineUserEventHandler(object sender, OnlineUserItemEventArgs e);

    public class OnlineUserItem
    {
        public int Count { get; set; }
        public string Id { get; set; }
        public string Name { get; set; }
        public DateTime LastVisitTime { get; set; }
    }

    public class OnlineUserManager
    {
        private System.Collections.Generic.Dictionary<string, OnlineUserItem> dict;

        private System.Threading.Timer timer;

        public static string ApplicationKey = "ApplicationKey";
        public static OnlineUserManager Current
        {
            get
            {
                return System.Web.HttpContext.Current.Application[ApplicationKey]
                    as OnlineUserManager;
            }
        }


        // 定时器的回调
        private void TimerCallback(Object state)
        {
            lock (this.dict)
            {
                string[] keys = new string[this.dict.Keys.Count];
                this.dict.Keys.CopyTo(keys, 0);

                DateTime now = DateTime.Now;
                TimeSpan span = new TimeSpan(0, 0, section.Timeout);

                foreach (string key in keys)
                {
                    // 已经过期
                    if ((now - this.dict[key].LastVisitTime) > span)
                    {
                        this.dict.Remove(key);
                    }
                }
            }
        }


        // 获取配置参数
        private static com.aspnet.OnlineUserConfigSection section =
            System.Web.HttpContext.Current.GetSection("OnlineUser")
                as com.aspnet.OnlineUserConfigSection;

        public static bool Enabled
        {
            get { return section.Enabled; }
        }

        public OnlineUserManager()
        {
            dict = new Dictionary<string, OnlineUserItem>();

            timer = new System.Threading.Timer(
                this.TimerCallback,
                null,
                section.Period,
                section.DueTime
                );
        }

        public bool CheckIn(OnlineUserItem item)
        {
            bool isNew = true;
            lock (this.dict)
            {
                if (dict.ContainsKey(item.Name))
                {
                    OnlineUserItem oldItem = dict[item.Name];
                    oldItem.Count++;
                    isNew = false;
                }
                else
                {
                    dict.Add(item.Name, item);
                }
            }
            return isNew;
        }

        public string[] GetOnlineUsers()
        {
            string[] nameArray = new string[this.dict.Count];
            int i = 0;
            foreach (OnlineUserItem item in this.dict.Values)
            {
                nameArray[i++] = item.Name;
            }

            return nameArray;
        }

    }

    public class OnlineUserModule : System.Web.IHttpModule
    {
        public event OnlineUserEventHandler UserCheckIn;

        protected void OnUserCheckIn(OnlineUserItemEventArgs e)
        {
            if (this.UserCheckIn != null)
            {
                this.UserCheckIn(this, e);
            }
        }

        #region IHttpModule 成员

        public void Dispose()
        {

        }

        public void Init(System.Web.HttpApplication application)
        {
            if (OnlineUserManager.Enabled)
            {
                application.PostAuthenticateRequest += new EventHandler(Application_PostAuthenticateRequest);
            }
        }

        void Application_PostAuthenticateRequest(object sender, EventArgs e)
        {
            System.Web.HttpContext context = System.Web.HttpContext.Current;
            System.Web.HttpRequest request = context.Request;
            System.Web.HttpResponse response = context.Response;

            //
            string userid = context.User.Identity.IsAuthenticated ?
                context.User.Identity.Name :
                context.Request.AnonymousID;

            System.Web.HttpApplicationState applicationState = context.Application;
            OnlineUserManager oum = applicationState[OnlineUserManager.ApplicationKey] as OnlineUserManager;

            OnlineUserItem item = new OnlineUserItem();
            System.Security.Principal.IIdentity identity = context.User.Identity;
            if (identity.IsAuthenticated)
            {
                item.Id = identity.Name;
                item.Name = identity.Name;
            }
            else
            {
                item.Id = context.Request.AnonymousID;
                item.Name = "匿名";
            }

            item.LastVisitTime = DateTime.Now;
            item.Count = 1;

            OnlineUserItemEventArgs args = new OnlineUserItemEventArgs();
            args.Item = item;

            if (oum.CheckIn(item))
            {
                this.OnUserCheckIn(args);
            }


        }

        #endregion
    }
}
